/*
 *  AS IS License 
 * ==Naive Coders==
 */
package com.naivecoders.refex.functions;

import com.naivecoders.refex.FunctionFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 *
 * @author andrew
 */
public enum FCode {

    A(AppendFunction.class), // append
    G(ArgumentFunction.class), // argument function
    R(ResolveFunction.class), // resolve by name
    I(InvokeFunction.class), // invoke 
    S(SubstituteArgumentsFunction.class),
    Z(IsEmptyFunction.class),
    P(PrependFunction.class),
    T(TailFunction.class), // tail
    H(HeadFunction.class), // head
    E(EqualsFunction.class), // equal
    C(IfFunction.class), // conditional
    Y(TrueFunction.class), // true function
    U(StripFunction.class),
    D(PrintFunction.class);
//    O, // open function as AST
//    N, // register function
//    F, //
//    V;
    private final char ch;
    private final Class<? extends AbstractFunction> funcClass;

    private FCode() {
        this(null);
    }

    private FCode(Class<? extends AbstractFunction> clz) {
        assert name().length() == 1;
        ch = name().charAt(0);
        funcClass = clz;
    }

    public AbstractFunction create(FunctionFactory factory) {
        try {
            if (funcClass == null) {
                return null;
            }
            final Constructor<? extends AbstractFunction> constructor = funcClass.getConstructor(FunctionFactory.class);
            return constructor.newInstance(factory);

        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex) {

            throw new RuntimeException(ex);
        }
    }

    public static FCode resolve(char v) {
        for (FCode fc : values()) {
            if (fc.ch == v) {
                return fc;
            }
        }
        return null;
    }
}
